org	0x7c00	
;----------------------类似于define,不占用空间，使用地方编译的时候会替换成相应的值-----------
BaseOfStack	equ	0x7c00

BaseOfLoader	equ	0x1000
OffsetOfLoader	equ	0x00

RootDirSectors	equ	14
SectorNumOfRootDirStart	equ	19
SectorNumOfFAT1Start	equ	1
SectorBalance	equ	17
;--------------------------end-----------------------------

;----------------fat12文件系统引导扇区结构,严格按照此结构进行编码,否则，系统不会将这个软盘识别为fat12---------------------------------
	jmp	short Label_Start
	nop
	;BS_OEMName	db	'MINEboot'
	BS_OEMName	db	"Lyfboot",0	
	BPB_BytesPerSec	dw	512
	BPB_SecPerClus	db	1
	BPB_RsvdSecCnt	dw	1
	BPB_NumFATs	db	2
	BPB_RootEntCnt	dw	224
	BPB_TotSec16	dw	2880
	BPB_Media	db	0xf0
	BPB_FATSz16	dw	9
	BPB_SecPerTrk	dw	18
	BPB_NumHeads	dw	2
	BPB_HiddSec	dd	0
	BPB_TotSec32	dd	0
	BS_DrvNum	db	0
	BS_Reserved1	db	0
	BS_BootSig	db	0x29
	BS_VolID	dd	0
	BS_VolLab	db	'boot loader'
	BS_FileSysType	db	'FAT12   '
	;---------------------------------------end-------------------------------
global Func_ReadOneSector
Label_Start:

	mov	ax,	cs
	mov	ds,	ax
	mov	es,	ax
	mov	ss,	ax
	mov	sp,	BaseOfStack

;=======	clear screen

	mov	ax,	0600h
	mov	bx,	0700h
	mov	cx,	0
	mov	dx,	0184fh
	int	10h

;=======	set focus

	mov	ax,	0200h
	mov	bx,	0000h
	mov	dx,	0000h
	int	10h

;=======	display on screen : Start Booting......

	mov	ax,	1301h
	mov	bx,	000fh
	mov	dx,	0000h
	mov	cx,	10
	push	ax
	mov	ax,	ds
	mov	es,	ax
	pop	ax
	mov	bp,	StartBootMessage
	int	10h

;=======	reset floppy

	xor	ah,	ah
	xor	dl,	dl
	int	13h

;=======	search loader.bin
	mov	word	[SectorNo],	SectorNumOfRootDirStart

Lable_Search_In_Root_Dir_Begin:

	cmp	word	[RootDirSizeForLoop],	0
	jz	Label_No_LoaderBin
	dec	word	[RootDirSizeForLoop]	
	mov	ax,	00h
	mov	es,	ax
	mov	bx,	8000h
	mov	ax,	[SectorNo]
	mov	cl,	1
	call	Func_ReadOneSector
	mov	si,	LoaderFileName
	mov	di,	8000h
	;修正方向，每执行一次lodsb,si会加1
	cld
	;一个扇区最多有16个目录结构 32*16=512
	mov	dx,	10h
	
Label_Search_For_LoaderBin:

	cmp	dx,	0
	jz	Label_Goto_Next_Sector_In_Root_Dir
	dec	dx
	;一个目录项的名字最多有11个字节，所以，最多比较11次
	mov	cx,	11

Label_Cmp_FileName:

	cmp	cx,	0
	;如果一个目录项比完了，说明完全吻合，-> 找到对应的目录项了
	jz	Label_FileName_Found
	dec	cx
	;将si指向的字节传送到al
	lodsb	
	cmp	al,	byte	[es:di]
	jz	Label_Go_On
	jmp	Label_Different

Label_Go_On:
	
	inc	di
	jmp	Label_Cmp_FileName

Label_Different:
	;因为不知道比到哪一个了字节了，也不知道偏移，将前面5个位置0,然后再加20h,就到了该扇区的下一个目录项
	and	di,	0ffe0h
	add	di,	20h
	mov	si,	LoaderFileName
	jmp	Label_Search_For_LoaderBin

Label_Goto_Next_Sector_In_Root_Dir:
	
	add	word	[SectorNo],	1
	jmp	Lable_Search_In_Root_Dir_Begin
	
;=======	display on screen : ERROR:No LOADER Found

Label_No_LoaderBin:

	mov	ax,	1301h
	mov	bx,	008ch
	mov	dx,	0100h
	mov	cx,	23
	push	ax
	mov	ax,	ds
	mov	es,	ax
	pop	ax
	mov	bp,	NoLoaderMessage
	int	10h
	jmp	$

;=======	found loader.bin name in root director struct

Label_FileName_Found:

	mov	ax,	RootDirSectors
;因为不知道比到哪一个了字节了，也不知道偏移，将前面5个位置0,然后再加1ah,就到了该项的首簇号的地址	
	and	di,	0ffe0h
	add	di,	01ah
	mov	cx,	word	[es:di]
	push	cx
	add	cx,	ax
	add	cx,	SectorBalance
	mov	ax,	BaseOfLoader
	mov	es,	ax
	mov	bx,	OffsetOfLoader
	mov	ax,	cx

Label_Go_On_Loading_File:
	push	ax
	push	bx
	mov	ah,	0eh
	;每读一个扇区都会再后面加上.表示进度条正在动
	mov	al,	'.'
	mov	bl,	0fh
	int	10h
	pop	bx
	pop	ax

	mov	cl,	1
	call	Func_ReadOneSector
	pop	ax
	;输入参数为首簇号
	call	Func_GetFATEntry
	;通过查看fat表，看看该簇号下的内容是什么，如果是0xfffh,则表示该文件已结束，否则就是下一块数据的簇号
	cmp	ax,	0fffh
	jz	Label_File_Loaded
	push	ax
	mov	dx,	RootDirSectors
	;真实的数据地址的首簇号为2,但是扇区号为 1(引导扇区) + 18(2个fat表) + 14(目录区 224项/16=14)
	;为什么是224项，看书,所以fat12文件系统目录区最多有14个扇区
	;所以簇号2的扇区号=1+18+14=33，所以，数据居的簇号和扇区号的关系为 扇区号-簇号 = 31
	;当然这里说的lba扇区号
	add	ax,	dx
	add	ax,	SectorBalance
	add	bx,	[BPB_BytesPerSec]
	jmp	Label_Go_On_Loading_File

Label_File_Loaded:
	;这里是段地址加偏移地址，比如1000h:0 等于1000h<<4 + 0 = 10000h
	jmp	BaseOfLoader:OffsetOfLoader

;=======	read one sector from floppy

Func_ReadOneSector:
	;当调用 ah=02h int 13h的时候只接受chs扇区号
	push	bp
	mov	bp,	sp
	sub	esp,	2
	mov	byte	[bp - 2],	cl
	push	bx
	;每个磁头有18个扇区
	mov	bl,	[BPB_SecPerTrk]
	div	bl
	inc	ah
	;这里算出的余数+1就是对应的lba扇区号
	mov	cl,	ah
	;商=磁头号
	mov	dh,	al
	;磁头号/2=柱面号
	shr	al,	1
	mov	ch,	al
	and	dh,	1
	pop	bx
	;0表示第1个软盘驱动器;128表示第1个硬盘驱动器 他们的区分在bit7上
	mov	dl,	[BS_DrvNum]
Label_Go_On_Reading:
	mov	ah,	2
	mov	al,	byte	[bp - 2]
	int	13h
	jc	Label_Go_On_Reading
	add	esp,	2
	pop	bp
	ret

;=======	get FAT Entry

Func_GetFATEntry:

	push	es
	push	bx
	push	ax
	mov	ax,	00
	mov	es,	ax
	pop	ax
	mov	byte	[Odd],	0
	;这里用首簇号*3/2表示该数据 商表示所在扇区，余数表示字节偏移
	mov	bx,	3
	mul	bx
	mov	bx,	2
	div	bx
	cmp	dx,	0
	jz	Label_Even
	;比如首簇号为0,则表示为偶数，Odd=0,反之Odd=1
	mov	byte	[Odd],	1

Label_Even:

	xor	dx,	dx
	mov	bx,	[BPB_BytesPerSec]
	div	bx
	push	dx
	mov	bx,	8000h
	add	ax,	SectorNumOfFAT1Start
	mov	cl,	2
	call	Func_ReadOneSector
	
	pop	dx
	;这里是将bx加上偏移，定位fat表所在数据项
	add	bx,	dx
	mov	ax,	[es:bx]
	cmp	byte	[Odd],	1
	jnz	Label_Even_2
	shr	ax,	4

Label_Even_2:
;如果取得值为0xfffh,则表示该文件结束了
	and	ax,	0fffh
	pop	bx
	pop	es
	ret

;=======	tmp variable

RootDirSizeForLoop	dw	RootDirSectors
SectorNo		dw	0
Odd			db	0

;=======	display messages

StartBootMessage:	db	"Start Boot",13,10
NoLoaderMessage:	db	"ERROR:No LOADER Found",13,10
LoaderFileName:		db	"LOADER  BIN",0

;=======	fill zero until whole sector

	times	510 - ($ - $$)	db	0
	dw	0xaa55

